package cn.com.lyj6851.auth.authentication;



import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.TokenRequest;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiaoleilu.hutool.map.MapUtil;

import cn.com.lyj6851.auth.utils.AuthUtils;
import cn.com.lyj6851.common.constant.CommonConstant;
import lombok.extern.slf4j.Slf4j;

/**
 * @author 登录成功处理器
 * 功能:通过请求参数: 
 *     构建出:OAuth2Request  Authentication
 * 用户登录成功后,生成一个token返回给调用方;
 * 调用方携带token来访问资源服务器保护的资源    
 */
@Slf4j
@Component
public class YongAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
	
		
	//private RequestCache requestCache = new HttpSessionRequestCache();
	
	public static final String BASIC_ = "Basic ";
	
	//private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
	
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private ClientDetailsService clientDetailsService;
    @Autowired
    private AuthorizationServerTokenServices authorizationServerTokenServices;
	@Autowired
	private PasswordEncoder passwordEncoder;
	//登录成功执行
	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) {
		log.info("登录成功!");
		// 获取请求头中的Authorization
		String header = request.getHeader("Authorization");
		// 是否以Basic开头
        if (header == null || !header.startsWith(BASIC_)) {
        	
        	//try {
        	SecurityContextHolder.clearContext();
				//redirectStrategy.sendRedirect(request, response, "/signOut");
			//} catch (IOException e) {
			//	e.printStackTrace();
			//} 
			throw new UnapprovedClientAuthenticationException("请求头中client信息不能为空!");
			
        }
        
        try {
        	 // Base64 解析请求头拿到clientid  client secret的数组
        	 String[] tokens = AuthUtils.extractAndDecodeHeader(header);
             assert tokens.length == 2;
             String clientId = tokens[0];
             String clientSecret = tokens[1];
             
             ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
             //校验secret
             if (clientDetails == null) {
                 throw new UnapprovedClientAuthenticationException("clientId对应的配置信息不存在:" + clientId);
                 //!clientDetails.getClientSecret().equals(clientSecret)
                 //passwordEncoder.matches(clientDetails.getClientSecret(), passwordEncoder.encode(clientSecret))
             } else if (passwordEncoder.matches(clientDetails.getClientSecret(), passwordEncoder.encode(clientSecret))) {
                 throw new UnapprovedClientAuthenticationException("clientSecret不匹配:" + clientId);
             }
             
             TokenRequest tokenRequest = new TokenRequest(MapUtil.newHashMap(), clientId, clientDetails.getScope(), "custom");
             
             //校验scope
             new DefaultOAuth2RequestValidator().validateScope(tokenRequest, clientDetails);
             
             OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
             OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
             OAuth2AccessToken oAuth2AccessToken = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
             log.info("获取token 成功：{}", oAuth2AccessToken.getValue());
             
             response.setCharacterEncoding(CommonConstant.UTF8);
             response.setContentType(CommonConstant.CONTENT_TYPE);
             
             PrintWriter printWriter = response.getWriter();
             printWriter.append(objectMapper.writeValueAsString(oAuth2AccessToken));
             
        }catch (IOException e) {
            throw new BadCredentialsException( "Failed to decode basic authentication token");
        }
		 
    }
}
